package com.datareport.config.datasource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * 数据源工具类
 * 提供数据源切换和管理的工具方法
 * 
 * @author datareport
 * @since 2024-01-01
 */
@Slf4j
@Component
public class DataSourceUtil {

    @Autowired
    @Qualifier("businessDataSource")
    private DataSource businessDataSource;

    @Autowired
    @Qualifier("statisticsDataSource")
    private DataSource statisticsDataSource;

    @Autowired
    @Qualifier("systemDataSource")
    private DataSource systemDataSource;

    @Autowired
    @Qualifier("dynamicDataSource")
    private DataSource dynamicDataSource;

    @Autowired
    @Qualifier("businessJdbcTemplate")
    private JdbcTemplate businessJdbcTemplate;

    @Autowired
    @Qualifier("statisticsJdbcTemplate")
    private JdbcTemplate statisticsJdbcTemplate;

    @Autowired
    @Qualifier("systemJdbcTemplate")
    private JdbcTemplate systemJdbcTemplate;

    /**
     * 获取当前使用的数据源类型
     */
    public DataSourceContextHolder.DataSourceType getCurrentDataSourceType() {
        return DynamicDataSource.getCurrentDataSourceType();
    }

    /**
     * 切换到业务数据库
     */
    public void switchToBusinessDB() {
        DynamicDataSource.switchToBusinessDb();
        log.info("切换到业务数据库");
    }

    /**
     * 切换到统计结果库
     */
    public void switchToStatisticsDB() {
        DynamicDataSource.switchToStatisticsDb();
        log.info("切换到统计结果库");
    }

    /**
     * 切换到系统配置库
     */
    public void switchToSystemDB() {
        DynamicDataSource.switchToSystemDb();
        log.info("切换到系统配置库");
    }

    /**
     * 清除当前数据源设置
     */
    public void clearDataSource() {
        DynamicDataSource.clearDataSource();
        log.info("清除当前数据源设置");
    }

    /**
     * 在指定数据源中执行操作
     */
    public <T> T executeWithDataSource(DataSourceContextHolder.DataSourceType dataSourceType, DataSourceCallback<T> callback) {
        DataSourceContextHolder.DataSourceType originalDataSource = DataSourceContextHolder.getDataSourceType();
        try {
            DataSourceContextHolder.setDataSourceType(dataSourceType);
            return callback.doInDataSource();
        } finally {
            if (originalDataSource != null) {
                DataSourceContextHolder.setDataSourceType(originalDataSource);
            } else {
                DataSourceContextHolder.clearDataSourceType();
            }
        }
    }

    /**
     * 获取指定数据源的JdbcTemplate
     */
    public JdbcTemplate getJdbcTemplate(DataSourceContextHolder.DataSourceType dataSourceType) {
        switch (dataSourceType) {
            case BUSINESS_DB:
                return businessJdbcTemplate;
            case STATISTICS_DB:
                return statisticsJdbcTemplate;
            case SYSTEM_DB:
                return systemJdbcTemplate;
            default:
                throw new IllegalArgumentException("不支持的数据源类型: " + dataSourceType);
        }
    }

    /**
     * 获取指定数据源的连接信息
     */
    public Map<String, Object> getDataSourceInfo(DataSourceContextHolder.DataSourceType dataSourceType) {
        DataSource dataSource = getDataSource(dataSourceType);
        Map<String, Object> info = new HashMap<>();
        
        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();
            info.put("url", metaData.getURL());
            info.put("user", metaData.getUserName());
            info.put("driverName", metaData.getDriverName());
            info.put("driverVersion", metaData.getDriverVersion());
            info.put("databaseProductName", metaData.getDatabaseProductName());
            info.put("databaseProductVersion", metaData.getDatabaseProductVersion());
            info.put("connection", connection.isValid(5));
        } catch (SQLException e) {
            log.error("获取数据源信息失败: {}", dataSourceType, e);
            info.put("error", e.getMessage());
        }
        
        return info;
    }

    /**
     * 测试所有数据源连接
     */
    public Map<String, Boolean> testAllDataSources() {
        Map<String, Boolean> results = new HashMap<>();
        
        for (DataSourceContextHolder.DataSourceType dataSourceType : DataSourceContextHolder.DataSourceType.values()) {
            boolean isValid = testDataSourceConnection(dataSourceType);
            results.put(dataSourceType.getCode(), isValid);
        }
        
        return results;
    }

    /**
     * 测试指定数据源连接
     */
    public boolean testDataSourceConnection(DataSourceContextHolder.DataSourceType dataSourceType) {
        DataSource dataSource = getDataSource(dataSourceType);
        
        try (Connection connection = dataSource.getConnection()) {
            boolean isValid = connection.isValid(5);
            log.info("数据源 {} 连接测试: {}", dataSourceType.getCode(), isValid ? "成功" : "失败");
            return isValid;
        } catch (SQLException e) {
            log.error("数据源 {} 连接测试失败: {}", dataSourceType.getCode(), e.getMessage());
            return false;
        }
    }

    /**
     * 获取指定数据源
     */
    private DataSource getDataSource(DataSourceContextHolder.DataSourceType dataSourceType) {
        switch (dataSourceType) {
            case BUSINESS_DB:
                return businessDataSource;
            case STATISTICS_DB:
                return statisticsDataSource;
            case SYSTEM_DB:
                return systemDataSource;
            default:
                throw new IllegalArgumentException("不支持的数据源类型: " + dataSourceType);
        }
    }

    /**
     * 数据源回调接口
     */
    @FunctionalInterface
    public interface DataSourceCallback<T> {
        T doInDataSource();
    }
}